#pragma once

/* We use the following libraries here: OpenGL [r0], GLUT [r1] and GLEW [r2].
 *
 * r0: OpenGL is a graphics API that offers access to the GPU on the computer. Several versions
 *     exist. Briefly, and also not very accurately, the 1.x branch offered only fixed function 
 *     access to the hardware, while 2.x offered access to the programmable pipeline while
 *     maintaining the fixed function bindings. 3.x versions have attempted to finally eschew
 *     of the fixed function inheritage while offering access to even more modern features. At the
 *     time of writing this OpenGL 4.0 is the latest version. The caveat is that it runs only
 *     on a fairly up-to-date hardware. OpenGL 3.0 is a nice compromise between bleeding edge and
 *     accessibility. OpenGL ES 2.0 is what is used on the current generation of embedded devices,
 *     smarthphones, tablets and such. We will not discuss features beyond or below what OpenGL 3.0 
 *     has to offer here.
 *
 * r1: GLUT GL Utility Toolkit is a cross-platform library that can be used to create
 *     a window with a bound gl-context in a straightforward manner. Supports simple input
 *     functionality. GLUT might not be what you want to use for windowing for a real production
 *     application, but is handy for prototyping and writing brief tutorials.
 *
 * r2: GLEW: The GL extension wrangler (http://glew.sourceforge.net). Simplifies the
 *     process of using OpenGL extensions and features. It does not expand the functionality
 *     of the GL implementation on the platform in any way, it merely makes using existing
 *     features more straightforward.
 */

#include <string>
#include <cstdlib>
#include <cstdio>
#include <cstring>




namespace GlApp{

class Configuration
{
public:
    class  Window
    {
    public:
        std::string& name(){return name_;}
        int&         width(){return width_;}
        int&         height(){return height_;}
        int&         handle(){return handle_;}
    private:
        int         width_;
        int         height_;
        int         handle_;
        std::string name_;
    };

    Configuration()
    {
        window_.height() = 480;
        window_.width() =  640;
        window_.name() = "App window";
    }

    Window& window(){return window_;}

private:
    Window      window_;
};

class AppState
{
    friend void updateAppState(AppState&);
public:
    AppState();

    /** Return elapsed time in milliseconds since start of application. */
    double elapsedTimeMs(){return elapsedTime_;}
    /** Return configuration */
    Configuration& configuration(){return configuration_;}

private:
    /** Update internal counters and such */
    void update();

    double        elapsedTime_;
    Configuration configuration_;

};

#ifndef GL_APP_MAIN

/* Define these functions in the application. */
void appConfigure(GlApp::Configuration& config);
void appInitialize(GlApp::AppState& state);
void appUpdate(GlApp::AppState& state);
void appFinalize(GlApp::AppState& state);
void appResize(GlApp::AppState& state,int width, int height);

#endif


}// GlApp

